package com.dd.cloud.user.service.doctor.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.UserConstants;
import com.dd.cloud.common.utils.DateUtils;
import com.dd.cloud.user.entity.doctor.PatientMedCardStudy;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.doctor.PatientMedCardStudyMapper;
import com.dd.cloud.user.req.aicms.AskDoctorParamsReq;
import com.dd.cloud.user.req.doctor.*;
import com.dd.cloud.user.req.pres.PresPatientReq;
import com.dd.cloud.user.res.doctor.PatientMedCardMobPageRes;
import com.dd.cloud.user.res.doctor.PatientMedCardPageRes;
import com.dd.cloud.user.service.doctor.IPatientMedCardStudyService;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.ObjectUtils;
import com.dd.cloud.common.utils.PinYinUtils;
import com.dd.cloud.common.utils.SerialNumberUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class PatientMedCardStudyServiceImpl extends ServiceImpl<PatientMedCardStudyMapper, PatientMedCardStudy> implements IPatientMedCardStudyService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 医生添加患者病历卡
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPatientMedCardStudy(PatientMedCardCreateReq req) {
        if (req.getBirthDate() == null) {
            if (req.getAgeNum() == null && req.getAgeType() == null) {
                throw new ZekeException(400, "出生日期或年龄数必须选择一个");
            }
            req.setBirthDate(DateUtils.byAgeNumAndAgeTypeToDate(req.getAgeNum(), req.getAgeType()));
        }
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        QueryWrapper<PatientMedCardStudy> qw = new QueryWrapper<>();
        qw.lambda().eq(PatientMedCardStudy::getDoctorId, loginInfo.getId());
        qw.lambda().eq(PatientMedCardStudy::getMobileNumber, req.getMobileNumber());
        qw.lambda().ne(PatientMedCardStudy::getStatus, UserConstants.MedCardStatus.DEL);
        PatientMedCardStudy pmc = getOne(qw);
        if (pmc == null) {
            pmc = new PatientMedCardStudy();
            BeanUtils.copyProperties(req, pmc);
            pmc.setCreateDate(LocalDateTime.now());
            pmc.setStatus(UserConstants.MedCardStatus.NORMAL);
            pmc.setNamePinyin(PinYinUtils.chineseToPinyinSell(req.getName()));
            String medNo = SerialNumberUtils.getInstance().medSerialNumber(redisTemplate);
            while (true) {
                qw.clear();
                qw.lambda().eq(PatientMedCardStudy::getMedId, medNo);
                List<PatientMedCardStudy> card = list(qw);
                if (card == null || card.isEmpty()) {
                    break;
                }
                medNo = SerialNumberUtils.getInstance().medSerialNumber(redisTemplate);
            }
            pmc.setMedId(medNo);
        } else {
            BeanUtils.copyProperties(req, pmc);
            pmc.setNamePinyin(PinYinUtils.chineseToPinyinSell(req.getName()));
        }
        pmc.setDoctorId(loginInfo.getId());
        pmc.setCreateId(loginInfo.getId());
        boolean flag = saveOrUpdate(pmc);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
    }

    /**
     * 添加患者病历卡信息
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPatientMedCardH5Study(PatientMedCardH5CreateReq req) {
        if (req.getBirthDate() == null) {
            if (req.getAgeNum() == null && req.getAgeType() == null) {
                throw new ZekeException(400, "出生日期或年龄数必须选择一个");
            }
            req.setBirthDate(DateUtils.byAgeNumAndAgeTypeToDate(req.getAgeNum(), req.getAgeType()));
        }
        QueryWrapper<PatientMedCardStudy> qw = new QueryWrapper<>();
        if (!StringUtils.isBlank(req.getMedId())) {
            qw.lambda().eq(PatientMedCardStudy::getMedId, req.getMedId());
        } else {
            qw.lambda().eq(PatientMedCardStudy::getMobileNumber, req.getMobileNumber());
        }
        qw.lambda().ne(PatientMedCardStudy::getStatus, UserConstants.MedCardStatus.DEL);
        PatientMedCardStudy pmc = getOne(qw);
        if (pmc == null) {
            pmc = new PatientMedCardStudy();
            BeanUtils.copyProperties(req, pmc);
            pmc.setCreateDate(LocalDateTime.now());
            pmc.setStatus(UserConstants.MedCardStatus.NORMAL);
            pmc.setNamePinyin(PinYinUtils.chineseToPinyinSell(req.getName()));
            String medNo = SerialNumberUtils.getInstance().medSerialNumber(redisTemplate);
            while (true) {
                qw.clear();
                qw.lambda().eq(PatientMedCardStudy::getMedId, medNo);
                List<PatientMedCardStudy> card = list(qw);
                if (card == null || card.isEmpty()) {
                    break;
                }
                medNo = SerialNumberUtils.getInstance().medSerialNumber(redisTemplate);
            }
            pmc.setMedId(medNo);
        } else {
            BeanUtils.copyProperties(req, pmc);
            pmc.setNamePinyin(PinYinUtils.chineseToPinyinSell(req.getName()));
        }
        pmc.setCreateId(req.getDoctorId());
        boolean flag = saveOrUpdate(pmc);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
    }

    /**
     * 修改就诊卡
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMedCardStudy(PatientMedCardUpdateReq req) {
        if (req.getBirthDate() == null) {
            if (req.getAgeNum() == null && req.getAgeType() == null) {
                throw new ZekeException(400, "出生日期或年龄数必须选择一个");
            }
            req.setBirthDate(DateUtils.byAgeNumAndAgeTypeToDate(req.getAgeNum(), req.getAgeType()));
        }
        //修改值
        PatientMedCardStudy pmc = getById(req.getId());
        if (pmc == null || pmc.getStatus() == UserConstants.MedCardStatus.DEL) {
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
        BeanUtils.copyProperties(req, pmc);
        pmc.setCreateDate(LocalDateTime.now());
        pmc.setNamePinyin(PinYinUtils.chineseToPinyinSell(pmc.getName()));
        boolean flag = updateById(pmc);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.OPER_ERROR);
        }
    }

    /**
     * 修改就诊卡状态
     *
     * @param id     就诊卡id
     * @param status 状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMedCardStatusStudy(Integer id, Integer status) {
        PatientMedCardStudy medCard = getById(id);
        if (medCard == null) {
            throw new ZekeException(400, "就诊卡不存在");
        }
        if (medCard.getStatus().equals(status)) {
            return;
        }
        if (!ObjectUtils.refrect(UserConstants.MedCardStatus.class, status)) {
            throw new ZekeException(ZkExceptionEnum.STATUS_DATA_ERROR);
        }
        medCard.setStatus(status);
        boolean i = updateById(medCard);
        if (!i) {
            throw new ZekeException(ZkExceptionEnum.DEL_ERROR);
        }
    }

    /**
     * 智能开方添加或修改就诊卡信息学习模式
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void aicmsSaveOrUpdateMedCard(AskDoctorParamsReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        QueryWrapper<PatientMedCardStudy> qw = new QueryWrapper<>();
        qw.lambda().eq(PatientMedCardStudy::getDoctorId, loginInfo.getId())
                .and(t -> t.eq(PatientMedCardStudy::getMedId, req.getMedId()).or().eq(PatientMedCardStudy::getMobileNumber, req.getLXDH()))
                .ne(PatientMedCardStudy::getStatus, UserConstants.MedCardStatus.DEL);
        //修改就诊卡
        PatientMedCardStudy patientMedCard = getOne(qw);
        if (patientMedCard == null) {
            patientMedCard = new PatientMedCardStudy();
            String medNo = SerialNumberUtils.getInstance().medSerialNumber(redisTemplate);
            while (true) {
                QueryWrapper<PatientMedCardStudy> qws = new QueryWrapper<>();
                qws.lambda().eq(PatientMedCardStudy::getMedId, medNo);
                int count = count(qws);
                if (count == 0) {
                    break;
                }
                medNo = SerialNumberUtils.getInstance().medSerialNumber(redisTemplate);
            }
            patientMedCard.setMedId(medNo);
            patientMedCard.setDoctorId(loginInfo.getId());
        }
        req.setMedId(patientMedCard.getMedId());
        patientMedCard.setDoctorId(loginInfo.getId());
        patientMedCard.setCreateId(loginInfo.getId());
        patientMedCard.setName(req.getXM());
        patientMedCard.setNamePinyin(PinYinUtils.chineseToPinyinSell(req.getXM()));
        patientMedCard.setContactAddress(req.getTXDZ());
        patientMedCard.setContagionHistory(req.getContagionHistory());
        patientMedCard.setDrugAllergyHistory(req.getDrugAllergyHistory());
        patientMedCard.setFamilyMedicalHistory(req.getFamilyMedicalHistory());
        patientMedCard.setMobileNumber(req.getLXDH());
        patientMedCard.setPregnant(req.getPregnant());
        patientMedCard.setNationality(req.getZB());
        patientMedCard.setMaritalStatus(req.getHYZK());
        patientMedCard.setIdCard(req.getIdCard());
        patientMedCard.setBirthDate(req.getBirthDate());
        patientMedCard.setSex(req.getXB());
        patientMedCard.setStatus(UserConstants.MedCardStatus.NORMAL);
        saveOrUpdate(patientMedCard);
    }

    /**
     * 查询病历卡分页
     *
     * @param req
     * @return
     */
    @Override
    public IPage<PatientMedCardPageRes> selPatientMedCardStudy(ParamsMedCardReq req) {
        LoginInfo li = UserInterceptor.getLoginUserInfo().get();
        if (li.getType() == LoginInfo.UserType.DOCTOR) {
            req.setDocId(li.getId());
        }
        Page<PatientMedCardPageRes> iPage = req.pagePojo();
        iPage = getBaseMapper().getPatientMedCardPageStudy(iPage, req);
        return iPage;
    }

    /**
     * 分页查询患者病历卡信息
     *
     * @param req
     * @return
     */
    @Override
    public IPage<PatientMedCardMobPageRes> selPatientMedCardMobPageStudy(ParamsMedCardMobPageReq req) {
        LoginInfo li = UserInterceptor.getLoginUserInfo().get();
        if (li.getType() == LoginInfo.UserType.DOCTOR) {
            req.setDocId(li.getId());
        }
        IPage<PatientMedCardMobPageRes> iPage = req.pagePojo();
        iPage = getBaseMapper().selPatientMedCardMobPageStudy(iPage, req);
        return iPage;
    }

    /**
     * 生成处方生成患者信息
     *
     * @param patientReq
     * @param loginInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PatientMedCardStudy addPresGeneratePatientInfo(PresPatientReq patientReq, LoginInfo loginInfo) {
        QueryWrapper<PatientMedCardStudy> qw = new QueryWrapper<>();
        qw.lambda().eq(PatientMedCardStudy::getDoctorId, loginInfo.getId())
                .eq(PatientMedCardStudy::getMobileNumber, patientReq.getMobileNumber())
                .ne(PatientMedCardStudy::getStatus, UserConstants.MedCardStatus.DEL);
        PatientMedCardStudy medCard = getOne(qw);
        if (medCard == null) {
            medCard = new PatientMedCardStudy();
            BeanUtils.copyProperties(patientReq, medCard);
            PatientMedCardCreateReq cardCreateReq = new PatientMedCardCreateReq();
            BeanUtils.copyProperties(patientReq, cardCreateReq);
            addPatientMedCardStudy(cardCreateReq);
            medCard.setMedId(cardCreateReq.getMedId());
        }
        return medCard;
    }
}
